#include "register.h"

#ifdef REG_DBG
#define dbg(...)		printf("# %s: ", __func__), printf(__VA_ARGS__)
#else
#define dbg(...)		
#endif

free_stack_l_t *free_stack_list;
reg_location_t *reg_alloc_table[MAX_REGISTERS];
reg_location_t **reg_master_table[MAX_TABLES];
int reg_caller_saved_id[MAX_REGISTERS];
reg_t reg_target;
int offset_count;
int reg_except[3];

int reg_saved = 0;
int reg_saved_r10;
int reg_saved_r11;

extern symboll_t **zzsymlist;

int free_stack_l_fetch(free_stack_l_t **ptr) {
	if((*ptr) == NULL) {
		return 0;
	}

	free_stack_l_t *tmp_ptr = *ptr;
	int tmp_offset = (*ptr)->offset;
	*ptr = (*ptr)->next;
	free(tmp_ptr);
	dbg("fetching %d\n", tmp_offset);

	return tmp_offset;
}

void free_stack_l_delete(free_stack_l_t **ptr) {
	dbg("deleting %d\n", (*ptr)->offset);
	fflush(stdout);
	free_stack_l_t *tmp = (*ptr);
	(*ptr) = (*ptr)->next;
	free(tmp);
}

free_stack_l_t **free_stack_l_contains(free_stack_l_t **ptr, int offset) {
	dbg("contains %d\n", offset);
	for(; (*ptr) != NULL; ptr = &((*ptr)->next)) {
		if((*ptr)->offset == offset) {
			dbg("\tyes\n");
			return ptr;
		}
	}

	dbg("\tno\n");
	return NULL;
}

free_stack_l_t **free_stack_l_add(free_stack_l_t **ptr, int offset) {
	dbg("adding %d\n", offset);
	free_stack_l_t *tmp_ptr = *ptr;
	*ptr = malloc(sizeof(free_stack_l_t));
	(*ptr)->offset = offset;
	(*ptr)->next = tmp_ptr;

	return ptr;
}

void free_stack_l_print(free_stack_l_t **ptr) {
	for(; (*ptr) != NULL; ptr = &((*ptr)->next)) {
		printf("%d\n", (*ptr)->offset);
	}
}

void stack_test(void) {
	free_stack_l_add(&free_stack_list, 0);
	free_stack_l_add(&free_stack_list, 2);
	free_stack_l_add(&free_stack_list, 3);
	free_stack_l_add(&free_stack_list, 4);
	free_stack_l_add(&free_stack_list, 6);
	free_stack_l_print(&free_stack_list);
	free_stack_l_t **tmp = free_stack_l_contains(&free_stack_list, 3);
	free_stack_l_delete(tmp);
	free_stack_l_print(&free_stack_list);
	tmp = free_stack_l_contains(&free_stack_list, 0);
	free_stack_l_delete(tmp);
	tmp = free_stack_l_contains(&free_stack_list, 6);
	free_stack_l_delete(tmp);
	free_stack_l_print(&free_stack_list);
	tmp = free_stack_l_contains(&free_stack_list, 2);
	free_stack_l_delete(tmp);
	tmp = free_stack_l_contains(&free_stack_list, 4);
	free_stack_l_delete(tmp);
	free_stack_l_print(&free_stack_list);
	if(free_stack_list == NULL)
		printf("Stack empty\n");
}

/* This should match the reg_t typedef */
char *reg_get_string(reg_t index) {
	switch(index) {
		case RDI:
			return "%rdi";
		case RSI:
			return "%rsi";
		case RDX:
			return "%rdx";
		case RCX:
			return "%rcx";
		case R8:
			return "%r8 ";
		case R9:
			return "%r9 ";
		case RAX:
			return "%rax";
		case R10:
			return "%r10";
		case R11:
			return "%r11";
		case ANY:
			return "ANY";
		default:
			return "OUT OF REG";
	}
}

char *reg_get_status(int index) {
	switch(index) {
		case LOADED:
			return "LOADED";
		case SPILLED:
			return "SPILLED";
		case NEW:
			return "NEW";
		default:
			return "STATUS UNKNOWN";
	}
}

char *reg_get_type(int index) {
	switch(index) {
		case VAR_T:
			return "VAR";
		case TMP_VAR_T:
			return "TMP_VAR";
		case TMP_T:
			return "TMP";
		default:
			return "TYPE UNKNOWN";
	}
}

reg_location_t *reg_get_ptr(int k) {
	int i = k/MAX_ENTRIES;
	int j = k%MAX_ENTRIES;

	if(reg_master_table[i][j]->reg != ANY) {
		if((reg_alloc_table[reg_master_table[i][j]->reg] != reg_master_table[i][j]) && (reg_master_table[i][j]->status != NEW)) {
			reg_print_all();
			ERR("MASTER / ALLOC TABLE INCONSISTENCY %d\n", k);
		}
	}

	return reg_master_table[i][j];
}

void reg_clean_vars() {
	for(int i=0; i<MAX_REGISTERS; i++) {
		if(reg_alloc_table[i] != NULL && reg_alloc_table[i]->type == VAR_T) {
			reg_alloc_table[i]->reg = ANY;
			reg_alloc_table[i] = NULL;
		}
	}
}

int reg_get_valid_offset(void) {
	if(free_stack_list != NULL) {
		int tmp_offset = free_stack_l_fetch(&free_stack_list);
		dbg("Returning offset from list %d\n", tmp_offset);
		return tmp_offset;
	}
	dbg("Returning offset on stack %d\n", (offset_count-1));
	return --offset_count;
}

void reg_prepare_free_register(reg_t wanted) {
	if(reg_alloc_table[wanted] != NULL) {
		/* Wanted register is in use .. */
		reg_location_t *ptr2 = reg_get_ptr(reg_alloc_table[wanted]->k);
		assert(ptr2 == reg_alloc_table[wanted]);

		if(ptr2->type == VAR_T) {
			/* .. and a variable, just overwrite it and mark it in the spilled variable */
			if(ptr2->status != SPILLED) {
				ERR("VARIABLE NOT DECLARED AS SPILLED\n");
			}
			ptr2->reg = ANY;
		} else if(ptr2->type == TMP_T || ptr2->type == TMP_VAR_T) {
			/* .. by some volatile value, spill it to the stack and rember it */
			ptr2->status = SPILLED;
			ptr2->reg = ANY;
			ptr2->offset = reg_get_valid_offset();
			dbg("Wanted reg occupied, spilling %d\n", ptr2->k);
			code("\t movq %s, %d(%%rbp)\n", reg_get_string(wanted), 8*(ptr2->offset));
		} else {
			ERR("DEAD END\n");
		}
	}
}

void reg_save_caller_saved(void) {
	if(reg_saved == 0) {
		reg_saved = 1;
		for(int i=0; i<MAX_REGISTERS; i++) {
			if(reg_alloc_table[i] != NULL) {
				reg_prepare_free_register(i);
				reg_alloc_table[i] = NULL;
			}
		}
	}
}

void reg_load_caller_saved(void) {
	if(reg_saved == 1) {
		reg_saved = 0;
	}
}

int reg_fetch_by_name(char *name) {
	symboll_t **ptr = contains(zzsymlist, name, 0, VARIABLE);
	return (*ptr)->reg_id;
}

reg_t reg_get_name(int k) {
	reg_location_t *ptr = reg_get_ptr(k);

	if(ptr->status == LOADED ) {
		//dbg("%d -> %s\n", k, reg_get_string(reg_master_table[i][j]->data.reg));
		return ptr->reg;
	} else if(ptr->type == VAR_T) {
		if(ptr->reg == ANY) {
			dbg("%d\n", k);
			reg_print_all();
			ERR("ATTEMPT TO REFERENCE NON LOADED REGISTER\n");
		}
		return ptr->reg;
	} else {
		dbg("%d\n", k);
		reg_print_all();
		ERR("DEAD END\n");
	}
	return ANY;
}

void reg_destroy(void) {
	for(int i=0; i<MAX_TABLES; i++) {
		if(reg_master_table[i] != NULL) {
			for(int j=0; j<MAX_ENTRIES; j++) {
				if(reg_master_table[i][j] != NULL) {
					free(reg_master_table[i][j]);
				}
			}
			dbg("Freeing table %d\n", i);
			free(reg_master_table[i]);
			reg_master_table[i] = NULL;
		}
	}
	for(int i=0; i<MAX_REGISTERS; i++) {
		reg_alloc_table[i] = NULL;
	}
	while(free_stack_list != NULL) {
		free_stack_l_delete(&free_stack_list);
	}
}

void reg_update_stack_offset(int offset) {
	if(offset == offset_count) {
		offset_count++;
		free_stack_l_t **tmp = free_stack_l_contains(&free_stack_list, offset_count);
		while(tmp != NULL) {
			free_stack_l_delete(tmp);
			offset_count++;
			tmp = free_stack_l_contains(&free_stack_list, offset_count);
		}
		dbg("\t and last on stack, %d\n", offset_count);
	} else {
		free_stack_l_add(&free_stack_list, offset);
	}
}

void reg_free(int k) {
	reg_location_t *ptr = reg_get_ptr(k);

	if(ptr->type == TMP_T) {
		dbg("Freeing %d\n", k);
		if(ptr->status == SPILLED) {
			dbg("\t was spilled\n");
			reg_update_stack_offset(ptr->offset);
		} else if(ptr->status == LOADED) {
			reg_t target = reg_get_name(k);
			dbg("\t was loaded\n");
			reg_alloc_table[target] = NULL;
		} else {
			dbg("%d %s\n", k, reg_get_status(k));
			ERR("ATTEMPT TO FREE REG_LOCATION WITH UNKNOWN STATUS\n");
		}
		for(int l=0; l<MAX_REGISTERS; l++) {
			if((ptr == reg_alloc_table[l]) && (ptr->type != VAR_T)) {
				reg_print_all();
				ERR("REGISTER WITH INCONSISTENT STATUS, IS LOADED BUT NOT DECLARED AS SUCH\n");
			}
		}

		int i = k/MAX_ENTRIES;
		int j = k%MAX_ENTRIES;
		free(reg_master_table[i][j]);
		reg_master_table[i][j] = NULL;

		int canary = 1;
		for(int l=0; l<MAX_ENTRIES; l++) {
			if(reg_master_table[i][l] != NULL) {
				canary = 0;
			}
		}

		if(canary == 1) {
			dbg("& freeing table %d\n", j);
			free(reg_master_table[i]);
			reg_master_table[i] = NULL;
		}
	} else if(ptr->type == VAR_T) {
		if(ptr->reg != ANY && reg_alloc_table[ptr->reg] == ptr) {
			reg_alloc_table[ptr->reg] = NULL;
			ptr->reg = ANY;
		}
	}
}

void reg_free_var(int k) {
	reg_location_t *ptr = reg_get_ptr(k);

	assert(ptr->type == VAR_T);

	for(int l=0; l<MAX_REGISTERS; l++) {
		if(ptr == reg_alloc_table[l]) {
			reg_alloc_table[l] = NULL;
		}
	}
	ptr->status = SPILLED;
	ptr->type = TMP_T;
	ptr->reg = ANY;

	reg_free(k);
}



int reg_get_free_register(void) {
	int l;
	for(l=0; l<MAX_REGISTERS; l++) {
		if(reg_alloc_table[l] == NULL) {
			break;
		}
	}
	if(l == MAX_REGISTERS) {
		int i = 0;
		l = ((reg_except[0]+reg_except[1]+reg_except[2])%MAX_REGISTERS);
		while(l == reg_except[0] || l == reg_except[1] || l == reg_except[2]) {
			i++;
			l = ((l+i)%MAX_REGISTERS);
		}
	}
	dbg("Determined %s\n", reg_get_string(l));
	return l;
}

void reg_load_var(int k, reg_t wanted) {
	dbg("VAR %d to %s\n", k, reg_get_string(wanted));
	reg_location_t *ptr = reg_get_ptr(k);

	if(wanted == ANY) {
		/* Assign any register */
		wanted = reg_get_free_register();
	}
	reg_prepare_free_register(wanted);
	/* wanted register is now free, move. */
	code("\t movq %d(%%rbp), %s\n", 8*(ptr->offset), reg_get_string(wanted));

	reg_alloc_table[wanted] = ptr;
	/* status is always spilled for variables */
	ptr->reg = wanted;
}

void reg_load_tmp(int k, reg_t wanted) {
	dbg("TMP %d to %s\n", k, reg_get_string(wanted));
	reg_location_t *ptr = reg_get_ptr(k);

	if(ptr->status == LOADED) {
		/* Load a variable that is already loaded */
		if((wanted == ANY) || (ptr->reg == wanted)) {
			/* in the correct register */
			dbg("%d already loaded, returning\n", k);
			return;
		}
		if(reg_alloc_table[wanted] != NULL) {
			/* wanted register in use */
			reg_location_t *ptr2 = reg_get_ptr(reg_alloc_table[wanted]->k);
			assert(ptr2 == reg_alloc_table[wanted]);

			if(ptr2->type == VAR_T) {
				/* .. and a variable, just overwrite it and mark it in the spilled variable */
				assert(ptr2->status == SPILLED);
				dbg("Is VAR overwriting\n");
				ptr2->status = SPILLED;
				ptr2->reg = ANY;
				reg_alloc_table[ptr->reg] = NULL;
				dbg("moving1 %d -> %s\n", k, reg_get_string(wanted));
				code("\t movq %s, %s\n", reg_get_string(ptr->reg), reg_get_string(wanted));
			} else if(ptr2->type == TMP_T || ptr2->type == TMP_VAR_T) {
				/* .. by some volatile value, swap it and rember it */
				dbg("Wanted reg in use by %d, swapping with %d\n", ptr2->k, k);
				code("\t pushq %s\n", reg_get_string(wanted));
				code("\t movq %s, %s\n", reg_get_string(reg_get_name(k)), reg_get_string(wanted));
				code("\t popq %s\n", reg_get_string(reg_get_name(k)));
				/* set the new register for the moved value */
				ptr2->reg = ptr->reg;
				/* set the new pointer in the reg_alloc_table */
				reg_alloc_table[ptr->reg] = ptr2;
			} else {
				ERR("DEAD END\n");
			}
		} else {
			dbg("moving2 %d -> %s\n", k, reg_get_string(wanted));
			code("\t movq %s, %s\n", reg_get_string(ptr->reg), reg_get_string(wanted));
			reg_alloc_table[ptr->reg] = NULL;
		}

	} else if(ptr->status == NEW || ptr->status == SPILLED) {
		/* New temporary variable */
		if(wanted == ANY) {
			wanted = reg_get_free_register();
		}
		reg_prepare_free_register(wanted);
		if(ptr->status == SPILLED) {
			/* wanted register is now free, move. */
			code("\t movq %d(%%rbp), %s\n", 8*(ptr->offset), reg_get_string(wanted));
			//free_stack_l_add(&free_stack_list, ptr->offset);
			reg_update_stack_offset(ptr->offset);
		}
	} else {
		ERR("TMP WITH INVALID STATUS\n");
	}
	reg_alloc_table[wanted] = ptr;
	ptr->status = LOADED;
	ptr->reg = wanted;
}

void reg_load(int k, reg_t wanted) {
	reg_location_t *ptr = reg_get_ptr(k);

	if(ptr->type == VAR_T) {
		reg_load_var(k, wanted);
	} else if(ptr->type == TMP_T || ptr->type == TMP_VAR_T) {
		reg_load_tmp(k, wanted);
	} else {
		ERR("DEAD END\n");
	}
}

int reg_allocate(reg_t wanted) {
	for(int i=0; i<MAX_TABLES; i++) {
		if(reg_master_table[i] != NULL) {
			for(int j=0; j<MAX_ENTRIES; j++) {
				if(reg_master_table[i][j] == NULL) {
					/* SUCCESS RETURN*/
					reg_master_table[i][j] = malloc(sizeof(reg_location_t));
					reg_location_t *ptr = reg_master_table[i][j];
					ptr->status = NEW;
					ptr->type = TMP_T;
					ptr->offset = 0;

					int k = (i*(MAX_ENTRIES))+j;
					ptr->k = k;
					ptr->reg = ANY;
					reg_load(k, wanted);

					return k;
				}
			}
			/* No more entries free in this table, check next one */
		} else {
			dbg("Creating new Table %d\n", i);
			reg_master_table[i] = malloc(MAX_ENTRIES*sizeof(reg_location_t *));
			for(int l=0; l<MAX_ENTRIES; l++) {
				reg_master_table[i][l] = NULL;
			}
			i--; /* Run the loop again, so the just created table gets selected */
		}
	}
	/* Checked all tables and nothing free, throw error */
	ERR("Ran out of space for variables.\n");
	return 0;
}

void reg_var_assign(reg_t wanted, int k) {
	dbg("Assign VAR to %s\n", reg_get_string(wanted));
	if(reg_alloc_table[wanted] != NULL) {
		reg_location_t *ptr = reg_get_ptr(k);
		reg_location_t *ptr2 = reg_get_ptr(reg_alloc_table[wanted]->k);
		if(ptr2->type == VAR_T) {
			/* if the assigned value is a variable, kick the other one, we assume that the newly assigned value is used next */
			if(ptr2->status != SPILLED) {
				ERR("VARIABLE NOT DECLARED AS SPILLED\n");
			}
			ptr2->reg = ANY;
		} else if((ptr2->type == TMP_T) || (ptr2->type == TMP_VAR_T)) {
			reg_free(ptr2->k);
		} else {
			ERR("DEAD END\n");
		}
		assert(ptr->status == SPILLED);
		assert(ptr->type == VAR_T);
		ptr->reg = wanted;
		reg_alloc_table[wanted] = ptr;
		code("\t movq %s, %d(%%rbp)\n", reg_get_string(wanted), 8*(ptr->offset));
	} else {
		ERR("ATTEMPT TO USE UNINITIALIZED REGISTER\n");
	}
}

int reg_var_allocate(reg_t wanted, int offset) {
	dbg("%s to VAR %d\n", reg_get_string(wanted), offset);
	if(reg_alloc_table[wanted] != NULL) {
		reg_location_t *ptr = reg_get_ptr(reg_alloc_table[wanted]->k);
		if(ptr->type == VAR_T) {
			/* if the assigned value is a variable, we need to copy it */
			ptr = reg_get_ptr(reg_pre_allocate(offset));
		}
		ptr->status = SPILLED;
		ptr->type = VAR_T;
		ptr->offset = offset;
		ptr->reg = ANY;
		code("\t movq %s, %d(%%rbp)\n", reg_get_string(wanted), 8*offset);
		return ptr->k;
	} else {
		ERR("ATTEMPT TO USE UNINITIALIZED REGISTER\n");
	}
}

int reg_arg_allocate(reg_t target) {
	//reg_print_all();
	//assert(free_stack_list == NULL);
	int arg_offset = --offset_count;//reg_get_valid_offset(); /*TODO*/

	return reg_var_allocate(target, arg_offset);
}

int reg_tmp_allocate(reg_t wanted) {
	if(reg_alloc_table[wanted] != NULL) {
		if(reg_alloc_table[wanted]->type == TMP_VAR_T) {
			reg_alloc_table[wanted]->type = TMP_T;
		}
		return reg_alloc_table[wanted]->k;
	} else {
		ERR("ATTEMPT TO USE UNINITIALIZED REGISTER\n");
	}
}

int reg_allocate_load1(reg_t wanted0, int k1, reg_t wanted1) {
	reg_location_t *ptr = reg_get_ptr(k1);

	if(ptr->type == TMP_VAR_T) {
		ptr->type = TMP_T;
	}

	reg_except[0] = wanted1;
	reg_except[1] = wanted1;
	reg_except[2] = wanted1;
	int k0 = reg_allocate(wanted0);
	reg_except[0] = reg_get_name(k0);
	reg_load(k1, wanted1);
	return k0;
}

void reg_load2(int k1, reg_t wanted1, int k2, reg_t wanted2) {
	reg_except[0] = wanted2;
	reg_except[1] = wanted2;
	reg_except[2] = wanted2;

	if(wanted1 == wanted2 && wanted1 != ANY) {
		ERR("WANTED LABEL1 == WANTED LABEL2\n");
	}

	if(reg_alloc_table[wanted1] != reg_get_ptr(k1)) {
		reg_load(k1, wanted1);
	}

	reg_except[0] = reg_get_name(k1);
	if(reg_alloc_table[wanted2] != reg_get_ptr(k2)) {
		reg_load(k2, wanted2);
	}
}

int reg_allocate_load2(reg_t wanted0, int k1, reg_t wanted1, int k2, reg_t wanted2) {
	reg_except[0] = wanted1;
	reg_except[1] = wanted1;
	reg_except[2] = wanted2;

	int k0 = reg_allocate(wanted0);

	reg_except[0] = reg_get_name(k0);
	reg_load(k1, wanted1);

	reg_except[1] = reg_get_name(k1);
	reg_load(k2, wanted2);

	return k0;
}

int reg_allocate_load_move2(reg_t wanted0, int k1, reg_t wanted1, int k2, reg_t wanted2) {
	reg_location_t *ptr = reg_get_ptr(k2);

	if(ptr->type == TMP_VAR_T) {
		ptr->type = TMP_T;
	}

	ptr = reg_get_ptr(k1);

	if((ptr->type == TMP_T || ptr->type == TMP_VAR_T) && (wanted0 == ANY)) {
		dbg("Using tmp register %d as dest\n", k1);
		reg_except[0] = wanted1;
		reg_except[1] = wanted1;
		reg_except[2] = wanted2;
		reg_load(k1, wanted1);
		ptr->type = TMP_VAR_T;

		reg_except[1] = reg_get_name(k1);
		reg_load(k2, wanted2);

		return k1;
	} else if((ptr->type == VAR_T) && (wanted0 == ANY)) {
		dbg("Using var register %d as dest\n", k1);
		reg_except[0] = wanted1;
		reg_except[1] = wanted1;
		reg_except[2] = wanted2;
		int k0 = reg_allocate(wanted1);

		reg_except[1] = reg_get_name(k0);
		reg_load(k2, wanted2);

		code("\t movq %d(%%rbp), %s\n", 8*ptr->offset, reg_get_string(reg_get_name(k0)));
		return k0;
	} else {//if(ptr->type == VAR_T) {
		int k0 = reg_allocate_load2(wanted0, k1, wanted1, k2, wanted2);
		code("\t movq %s, %s\n", reg_get_string(reg_get_name(k1)), reg_get_string(reg_get_name(k0)));
		return k0;
	//} else {
	//	ERR("REG LOCATION TYPE UNKNOWN\n");
	}
	return 0;
}

int reg_pre_allocate(int offset) {
	for(int i=0; i<MAX_TABLES; i++) {
		if(reg_master_table[i] != NULL) {
			for(int j=0; j<MAX_ENTRIES; j++) {
				if(reg_master_table[i][j] == NULL) {
					/* SUCCESS RETURN*/
					reg_master_table[i][j] = malloc(sizeof(reg_location_t));
					reg_location_t *ptr = reg_master_table[i][j];
					ptr->status = SPILLED;
					ptr->type = VAR_T;
					ptr->offset = offset;

					int k = (i*(MAX_ENTRIES))+j;
					ptr->k = k;
					ptr->reg = ANY;

					return k;
				}
			}
			/* No more entries free in this table, check next one */
		} else {
			dbg("Creating new Table %d\n", i);
			reg_master_table[i] = malloc(MAX_ENTRIES*sizeof(reg_location_t *));
			for(int l=0; l<MAX_ENTRIES; l++) {
				reg_master_table[i][l] = NULL;
			}
			i--; /* Run the loop again, so the just created table gets selected */
		}
	}
	/* Checked all tables and nothing free, throw error */
	ERR("Ran out of space for variables.\n");
	return 0;
}

void reg_print_all(void) {
	printf("## Register allocation ##\n");
	for(int i=0; i<MAX_REGISTERS; i++) {
		if(reg_alloc_table[i] != NULL) {
			printf("#\treg_id %s \t%s \t-> %d\n", reg_get_type(reg_alloc_table[i]->type), reg_get_string(i), reg_alloc_table[i]->k);
		} else {
			printf("#\treg_id \t\t%s \t-> NULL\n", reg_get_string(i));
		}
	}

	printf("## Whole map ##\n");
	for(int i=0; i<MAX_TABLES; i++) {
		if(reg_master_table[i] != NULL) {
			for(int j=0; j<MAX_ENTRIES; j++) {
				if(reg_master_table[i][j] != NULL) {
					if(((i*MAX_ENTRIES)+j) != reg_master_table[i][j]->k) {
						ERR("INCONSISTENT k %d calculated %d\n", reg_master_table[i][j]->k, ((i*MAX_ENTRIES)+j));
					}

					if(reg_master_table[i][j]->status == SPILLED) {
						printf("#\treg_id %s \t%d \ts> %d %s\n", reg_get_type(reg_master_table[i][j]->type), reg_master_table[i][j]->k, reg_master_table[i][j]->offset, reg_get_string(reg_master_table[i][j]->reg));
					} else if(reg_master_table[i][j]->status == NEW) {
						printf("#\treg_id %s \t%d \tn> %s\n", reg_get_type(reg_master_table[i][j]->type), reg_master_table[i][j]->k, reg_get_string(reg_master_table[i][j]->reg));
					} else if(reg_master_table[i][j]->status == LOADED) {
						printf("#\treg_id %s \t%d \t-> %s\n", reg_get_type(reg_master_table[i][j]->type), reg_master_table[i][j]->k, reg_get_string(reg_master_table[i][j]->reg));
					} else {
						ERR("UNKNOWN STATUS\n");
					}
				}
			}
			/* No more entries free in this table, check next one */
		}
	}
}
